import numpy as np


class Matrix:

    def __init__(self, list2d):  # 传入二维列表
        self.__values = [row[:] for row in list2d]

    def __repr__(self):
        return "Matrix({})".format(self.__values)

    def __str__(self):
        s = ''
        for row in self.__values:
            for e in row:
                s = s + str(e) + '\t'
            s += '\n'
        return s

    # 矩阵形状
    def shape(self):
        # 行数，列数
        return len(self.__values), len(self.__values[0])

    # 矩阵元素个数
    def size(self):
        r, c = self.shape()
        return r * c

    def __len__(self):
        return len(self.__values)

    # 获得矩阵中的元素
    def __getitem__(self, pos):
        r, c = pos  # 元组
        return self.__values[r][c]

    # 获得行向量
    def row_vector(self, index):
        return np.array(self.__values[index])

    # 获得列向量
    def column_vector(self, index):
        return np.array([row[index] for row in self.__values])

    # 矩阵加法
    def __add__(self, other):
        assert self.shape() == other.shape(), \
            "矩阵形状不匹配"
        return Matrix([[a + b for a, b in zip(self.row_vector(i), other.row_vector(i))]
                       for i in range(len(self))])

    # 矩阵减法
    def __sub__(self, other):
        assert self.shape() == other.shape(), \
            "矩阵形状不匹配"
        return Matrix([[a - b for a, b in zip(self.row_vector(i), other.row_vector(i))]
                       for i in range(len(self))])

    # 数量乘法
    def __mul__(self, k):
        return Matrix([[e * k for e in self.row_vector(i)]
                       for i in range(len(self))])

    def __rmul__(self, k):
        return self * k

    # 数量除法
    def __truediv__(self, k):
        assert k != 0, \
            "除数不能为0"
        return self * (1 / k)

    # 矩阵取正的结果
    def __pos__(self):
        return self*1

    # 矩阵取负的结果
    def __neg__(self):
        return self*(-1)

    # 构造零矩阵
    @classmethod
    def zero(cls,r,c):
        return cls([[0]*c for _ in range(r)])

    # 矩阵乘法
    def dot(self,other):
        if isinstance(other,np.ndarray):
            # 矩阵跟向量乘法
            assert self.column_vector() == len(other),\
                "矩阵列数不匹配"
            return np.dot(self.__values,other)
        if isinstance(other,Matrix):
            # 矩阵跟矩阵乘法
            assert self.shape()[1] == other.shape()[0],\
                "矩阵行数不匹配"
            return Matrix([[sum([e1*e2 for e1,e2 in zip(self.row_vector(i),other.row_vector(j))])
                           for j in range(other.shape()[0])]
                          for i in range(self.shape()[0])])


if __name__ == '__main__':
    # mat1 = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
    mat1 = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    print(mat1)
    # print(mat1.shape())
    # print(mat1.size())
    # print(len(mat1))
    # print(mat1[2,2])
    # print(mat1.row_vector(1))
    # print(mat1.column_vector(1))
    # print(mat1 * 3)
    # print(3 * mat1)
    # print(-mat1)
    # print(Matrix.zero(38,42))
    print(mat1.dot(mat1))
